package com.strongbj.iot.devices.newlight.response.coder;

import com.strongbj.iot.devices.newlight.message.NewLightReaderMessage;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;

public class NewLightReaderDecoder extends DelimiterBasedFrameDecoder {

	public NewLightReaderDecoder(int maxFrameLength) {
		super(maxFrameLength, Unpooled.copiedBuffer(new byte[] { (byte) 0x5a, (byte) 0xa5 })); // 通过5A A5解决粘包问题
	}

	// private static final int RESERVATIONS_SIZE = 15; // 数据保留区长度

	private static final int CRC_SIZE = 2; // 效验码的长度

	private static final int Time_SIZR = 4; // 时间戳的长度

	// 头部起始码 0x5a 0xa5
	private static final int HEADER_SIZE = 6; // 数据头的长度

	// private static final int VALID_LENGHT = HEADER_SIZE + RESERVATIONS_SIZE +
	// CRC_SIZE; // 有效长度

	private static final int VALID_LENGHT = HEADER_SIZE + CRC_SIZE; // 有效长度

	// 地址码
	private byte[] address = new byte[3];

	// 类型码
	private byte type;

	// 数据长度
	@SuppressWarnings("unused")
	private short length;

	@SuppressWarnings("unused")
	private byte tFrame;

	@SuppressWarnings("unused")
	private byte cFrame;

	private byte[] body = new byte[0];

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		super.channelInactive(ctx);
		ByteBuf bf = this.internalBuffer();
		bf.release();
	}

	@Override
	protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
		super.decode(ctx, in); // 通过A5 5A协议头来拆包

		if (in == null || in.readableBytes() == 0) {
			return in;
		}

		if (this.body != null) {
			// 可读信息段比头部信息小
			if (in.readableBytes() < VALID_LENGHT) {
				return null;
			}
			in.readBytes(address);
			type = in.readByte();
			length = in.readShort();
			tFrame = in.readByte();
			cFrame = in.readByte();
		}

		if (in.readableBytes() < length+CRC_SIZE + Time_SIZR) {
			this.body = null;
			return null;
		}

		// 读取正文
		this.body = new byte[length];
		in.readBytes(body);

		// 读取时间戳
		byte[] encryptionTime = new byte[Time_SIZR];
		in.readBytes(encryptionTime);
		
		byte[] crc = new byte[CRC_SIZE];
		in.readBytes(crc);
		
		NewLightReaderMessage message = new NewLightReaderMessage(address, type, body, encryptionTime);
		return message;
	}
}
